/*
 * Copyright (C) 2004 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.util;

import java.util.Properties;
import java.io.*;

/**
 * A properties class that reads/writes the properties from a file.
 * <ol>
 * <li>First it looks for a system property called 'config.properties' which
 * names the properties file. This can be specified when invoking the JVM with a
 * -D option thus: <br />
 * <code>java -Dconfig.properties=/myplace/mypropertyfile.ini myapplication</code>
 * </li>
 * <li>If that does not work it looks in the user home directory for a file
 * named <code>zoom.properties</code> (home directory on windows 95/98 is
 * C:\windows).</li>
 * <li>If that also fails it looks in the current directory for a file named
 * <code>zoom.properties</code></li>
 * <li>If that fails it tries to load a resource file named
 * <code>zoom.properties</code> using the classloader. That is, it looks for
 * the file in the classpath.</li>
 * <li>If that also fails it will give up and <emp>exit </emp>. Which means
 * that the application will stop.</li>
 * </ol>
 * The properties can be made persistant by calling the usual
 * java.util.Properties.store(OutputStream, String) method. This class also
 * provides a store method without parameters. If the no-parameters store is
 * called the properties will be saved to the same file found as described
 * above. If no file was found the class assumes the file to be called
 * <code>zoom.properties</code> and to reside in the current directory. Notice
 * that if the file was loaded from the classpath as a resource the store method
 * might not be able to write to it, so it will write to a file in the current
 * directory instead.
 * 
 * @author $Author: johan $
 * @version $Revision: 1.2 $
 */

public class Config extends Properties
{
	private static final long serialVersionUID = 1622735858880022226L;
	private static final String RESOURCE_NAME = "zoom.properties";
	private static Config instance = null;
	private String filename;

	/**
	 * Constructor for the Config object
	 */
	private Config() {
		super();
	}

	/**
	 * Save the properties to the same place from where they was read. If the
	 * properties was loaded as a resource using the classloader they will be
	 * stored in the current directory. This will mean that they are <emp>not
	 * </emp> stored in the same place and they will not be loadable as a
	 * resource.
	 */
	public void store() throws IOException
	{
		FileOutputStream out = new FileOutputStream(filename);
		super.store(out, "Configuration data");
	}

	/**
	 * Gets the Instance of the Config class.
	 * 
	 * @return The Instance value
	 */
	public static synchronized Config getInstance()
	{
		if (instance == null) {
			String tmpFilename = null;
			File file = null;
			tmpFilename = System.getProperty("config.properties");
			if (tmpFilename == null) {
				tmpFilename = System.getProperty("user.home") + File.separator
						+ RESOURCE_NAME;
				file = new File(tmpFilename);
				if (!file.exists()) {
					tmpFilename = System.getProperty("user.dir")
							+ File.separator + RESOURCE_NAME;
				}
			}
			instance = new Config();
			instance.filename = tmpFilename;
			file = new File(tmpFilename);
			if (file.exists()) {
				try {
					instance.load(new FileInputStream(file));
				} catch (IOException exc) {
					System.err.println("Unable to load configuration.");
					exc.printStackTrace();
					System.exit(-1);
				}
			} else {
				InputStream ins = Config.class.getClassLoader()
						.getResourceAsStream(RESOURCE_NAME);
				if (ins != null) {
					try {
						instance.load(ins);
					} catch (IOException exc) {
						System.err.println("Unable to load configuration.");
						exc.printStackTrace();
						System.exit(-1);
					}
				} else {
					System.err.println("Unable to load configuration.");
					System.exit(-1);
				}
			}
		}
		return instance;
	}
}